10996. Проверка
авиамаршрутов
Имеются n городов и m
авиарейсов. Ваша задача – определить, можно ли, используя доступные рейсы,
добраться из любого города в любой другой.
Вход. Первая строка содержит два целых
числа n и m – количество городов и рейсов. Города пронумерованы целыми
числами 1, 2, ..., n.
Далее следуют m строк с
описанием перелётов. Каждая строка содержит два целых числа a и b,
означающих, что существует рейс из города a в город b. Все рейсы
являются односторонними.
Выход. Выведите “YES”, если все маршруты
возможны, и “NO” в противном случае. В последнем случае также выведите два
города a и b, между которыми невозможно совершить
путешествие.
|
Пример
входа |
Пример
выхода |
|
4 5 1 2 2 3 3 1 1 4 3 4 |
NO 4 2 |
графы,
сильная связность
В задаче следует вывести “YES”, если граф является сильно связным. Граф называется сильно связным, если для любой
его вершины v выполняются следующие условия:
·
из вершины v достижимы все
остальные вершины графа;
·
вершина v достижима из любой
другой вершины. Иными словами, из любой вершины существует путь в v, что
эквивалентно достижимости по обратным рёбрам.
Зафиксируем
вершину v = 1 и проверим выполнение этих условий.
Реализация алгоритма
Входной граф храним в
списке смежности g. Обратный граф храним в списке смежности gr.
vector<vector<int>
> g, gr;
vector<int> used;
Функция dfs1 выполняет обход графа в глубину.
void dfs1(int v)
{
used[v] = 1;
for (int to : g[v])
if (!used[to]) dfs1(to);
}
Функция dfs2 выполняет обход графа в глубину на
обратном графе.
void dfs2(int v)
{
used[v] = 1;
for (int to : gr[v])
if (!used[to]) dfs2(to);
}
Основная часть программы. Читаем входные данные. Строим обратный граф.
scanf("%d %d", &n, &m);
g.resize(n + 1);
gr.resize(n + 1);
for (i = 0; i < m; i++)
{
scanf("%d %d", &a, &b);
g[a].push_back(b);
gr[b].push_back(a);
}
Запускаем поиск в глубину в исходном графе, начиная с вершины 1.
used.resize(n + 1);
dfs1(1);
for (i = 1; i <= n; i++)
if (used[i] == 0) break;
Если вершина i недостижима (used[i] = 0), то перемещение между
городами 1 и i невозможно.
if (i <= n)
{
printf("NO\n%d %d\n", 1,
i);
return 0;
}
Запускаем поиск в глубину на обратном графе, начиная с вершины 1.
used.clear();
used.resize(n + 1);
dfs2(1);
for (i = 1; i <= n; i++)
if (used[i] == 0) break;
Если вершина i недостижима из 1 в обратном графе (used[i] =
0), то перемещение между городами i и 1 невозможно.
if (i <= n)
{
printf("NO\n%d %d\n", i,
1);
return 0;
}
Граф является сильно связным. Выводим сообщение “YES”.
printf("YES\n");